/*************************************************
Author: will
Date: 10/22/2012
Description:
Notes: 
*************************************************/

#ifndef __CInstanceConfig_h__
#define __CInstanceConfig_h__

#include "CTArray.h"
#include "CTHashObjectMgr.h"
#include "commclass.h"
#include "commerrno.h"
#include "../item/CDropItemSubType.h"

class CInstanceDropSingleItem
{
public:
	CInstanceDropSingleItem() 
    {
	}

	virtual ~CInstanceDropSingleItem() 
    {
	}

public:
    unsigned char _ucItemType;
    unsigned int  _uiItemID;
    unsigned short _usItemCount;
};

class CInstanceGradeBonusConfigDetail
{
public:
    CInstanceGradeBonusConfigDetail()
    {
        _usNeedGrade = 0;
        _usGiftConfigID = 0;
    }

public:
    unsigned short _usNeedGrade; //所需要的累计评分
    unsigned short _usGiftConfigID; //礼包ID
};  

//星级评分奖励
class CInstanceGradeBonusConfigData
{
public:
    CInstanceGradeBonusConfigData()
        :_bHasConfig(false)
    {

    }

public:
    bool _bHasConfig;
    
    int _iBonusID;
    CTLib::CTArray<CInstanceGradeBonusConfigDetail, MAX_GRADE_BONUS_COUNT_PER_MAP> _astGradeConfigs;    //奖励信息
    CTLib::CTArray<unsigned short, MAX_INSTANCE_COUNT_PER_GRADE_BONUS> _ashIncludeInstanceID;       //该奖励所对应的副本ID
};

class CInstanceGradeBonusConfig
{
public:
    CInstanceGradeBonusConfig()
    {

    }

    int AddConfig(CInstanceGradeBonusConfigData& stConfigData)
    {
        if (stConfigData._iBonusID <= 0 || stConfigData._iBonusID >= _astConfigDatas.GetCount()
            || _astConfigDatas[stConfigData._iBonusID]._bHasConfig)
        {
            CT_ERROR(("%d", stConfigData._iBonusID));
            return RET_SYS_ERROR;
        }

        _astConfigDatas[stConfigData._iBonusID] = stConfigData;
        _astConfigDatas[stConfigData._iBonusID]._bHasConfig = true;
        return 0;
    }

    int GetConfig(int iBonusID, CInstanceGradeBonusConfigData& stConfigData)
    {
        stConfigData._iBonusID = iBonusID;
        if (stConfigData._iBonusID <= 0 || stConfigData._iBonusID >= _astConfigDatas.GetCount()
            || !_astConfigDatas[stConfigData._iBonusID]._bHasConfig)
        {
            CT_ERROR(("%d", stConfigData._iBonusID));
            return RET_SYS_ERROR;
        }

        stConfigData = _astConfigDatas[stConfigData._iBonusID];
        return 0;
    }

    int AddIncludeInstance(int iBonusID, unsigned short usInstanceID)
    {
        if (iBonusID <= 0)
        {
            return 0;
        }

        if (iBonusID <= 0 || iBonusID >= _astConfigDatas.GetCount()
            || !_astConfigDatas[iBonusID]._bHasConfig)
        {
            CT_ERROR(("%d", iBonusID));
            return RET_SYS_ERROR;
        }

        _astConfigDatas[iBonusID]._ashIncludeInstanceID.AddOneItem(usInstanceID);
        return 0;
    }

    CTLib::CTArray<CInstanceGradeBonusConfigData, MAX_GRADE_BONUS_COUNT + 1> _astConfigDatas;
};

class CInstanceFirstAccomplishBonusConfigData //首次通关奖励
{
public:
    CInstanceFirstAccomplishBonusConfigData()
    {

    }

    virtual ~CInstanceFirstAccomplishBonusConfigData()
    {

    }

public:
    unsigned int _uiBonusID;
    CTLib::CTArray<CInstanceDropSingleItem, MAX_INSTANCE_FIRST_ACCOMPLISH_BONUS_COUNT> _astDropItems;
};

class CInstanceFirstAccomplishBonusConfig
{
public:
    typedef CTLib::CTHashObjectMgr<unsigned int, CInstanceFirstAccomplishBonusConfigData> T_FIRST_ACCOMPLISH_BONUS_CONFIG_HASH;

    CInstanceFirstAccomplishBonusConfig()
    {

    }

    virtual ~CInstanceFirstAccomplishBonusConfig()
    {

    }

    static size_t CountSize()
    {
        return T_FIRST_ACCOMPLISH_BONUS_CONFIG_HASH::CountSize(MAX_INSTANCE_FIRST_ACCOMPLISH_BONUS_CFG_COUNT);
    }

    int Init(const char* sBuff)
    {
        return _stFirstAccomplishBonusHash.Init(sBuff, MAX_INSTANCE_FIRST_ACCOMPLISH_BONUS_CFG_COUNT);
    }

    int AddConfig(CInstanceFirstAccomplishBonusConfigData& stConfigData)
    {
        int iIndex = _stFirstAccomplishBonusHash.HashFind(stConfigData._uiBonusID);
        if (iIndex >= 0)
        {
            CT_ERROR(("add duplicate bonus %u", stConfigData._uiBonusID));
            return RET_SYSTEM_FAIL;
        }

        iIndex = _stFirstAccomplishBonusHash.HashAlloc(stConfigData._uiBonusID);
        if (iIndex < 0)
        {
            CT_ERROR(("bonus hash is full"));
            return RET_SYSTEM_FAIL;
        }

        _stFirstAccomplishBonusHash[iIndex] = stConfigData;
        return 0;
    }

    int GetConfig(unsigned int uiBonusID, CInstanceFirstAccomplishBonusConfigData& stConfigData)
    {
        int iIndex = _stFirstAccomplishBonusHash.HashFind(uiBonusID);
        if (iIndex < 0)
        {
            CT_ERROR(("%d", uiBonusID));
            return ERROR_INSTANCE_NO_FIRST_BONUS_ID;
        }

        stConfigData = _stFirstAccomplishBonusHash[iIndex];
        return 0;
    }

public:
    T_FIRST_ACCOMPLISH_BONUS_CONFIG_HASH _stFirstAccomplishBonusHash;
};

class CInstanceDropItemConfigData
{
public:
    CInstanceDropItemConfigData()
    {
        _ucDropItemType = 0;
        _szDropItemSubType.Set("%s","");
        _usDropItemConfigID = 0;
        _uiDropRate = 0;
        _iDropCount = 0;
    }

    virtual ~CInstanceDropItemConfigData()
    {
        
    }

public:
    unsigned char                               _ucDropItemType;
    unsigned short                              _usDropItemConfigID;
    CDropItemSubTypeConfigData::T_DROP_ITEM_SUBTYPE_CONFIG_KEY _szDropItemSubType;
    unsigned int                                _uiDropRate;
    int                                         _iDropCount;
};

class CInstanceConfigData
{
public:
    typedef CTLib::CTArray<unsigned short, 100> T_ALL_DROP_ITEM_CONFIG_ID;      //单副本所有可能掉落的物品ID
    typedef CTLib::CTArray<unsigned int, MAX_MONSTER_GROUP_PER_INSTANCE> T_INSTANCE_MONSTER_GROUP_IDS;
    typedef CTLib::CTArray<unsigned short, MAX_MONSTER_GROUP_PER_INSTANCE> T_INSTANCE_MONSTER_GROUP_LEVELS; //怪物等级
    typedef CTLib::CTArray<unsigned char, MAX_MONSTER_GROUP_PER_INSTANCE> T_INSTANCE_MONSTER_GROUP_POS; //怪物位置
    typedef CTLib::CTArray<CInstanceDropItemConfigData, DROP_ITEM_CFG_DROP_ITEM_COUNT_PER_GROUP> T_DROP_ITEM_GROUP_CONFIG;

    enum INSTANCE_TYPE
    {
        INSTANCE_TYPE_MIN  = 1,        //   

        INSTANCE_TYPE_MAIN = 1,        //主线副本
        INSTANCE_TYPE_CHALLENGE = 2,   //挑战副本(必须要是长线副本的最后一个，因为写死了一个算法)

        //INSTANCE_TYPE_ELITE = 3,       //精英副本
        INSTANCE_TYPE_MUSEUM = 4,      //博物馆

        INSTANCE_TYPE_SECRET_BEGIN = 5,
        INSTANCE_TYPE_SECRET_LV20       = 5,      //20级秘境
        INSTANCE_TYPE_SECRET_LV20_HARD  = 6,      //20级秘境(困难)
        INSTANCE_TYPE_SECRET_LV40       = 7,      //40级秘境
        INSTANCE_TYPE_SECRET_LV40_HARD  = 8,      //40级秘境(困难)
        INSTANCE_TYPE_SECRET_LV60       = 9,      //60级秘境
        INSTANCE_TYPE_SECRET_LV60_HARD  = 10,      //60级秘境(困难)
        INSTANCE_TYPE_SECRET_LV80       = 11,      //80级秘境
        INSTANCE_TYPE_SECRET_LV80_HARD  = 12,      //80级秘境(困难)
        INSTANCE_TYPE_SECRET_LV100       = 13,      //100级秘境
        INSTANCE_TYPE_SECRET_LV100_HARD  = 14,      //100级秘境(困难)
        INSTANCE_TYPE_SECRET_LV120       = 15,      //120级秘境
        INSTANCE_TYPE_SECRET_LV120_HARD  = 16,      //120级秘境(困难)
        INSTANCE_TYPE_SECRET_LV140       = 17,      //140级秘境
        INSTANCE_TYPE_SECRET_LV140_HARD  = 18,      //140级秘境(困难)
        INSTANCE_TYPE_SECRET_LV160       = 19,      //160级秘境
        INSTANCE_TYPE_SECRET_LV160_HARD  = 20,      //160级秘境(困难)
        INSTANCE_TYPE_SECRET_END = 20,

        INSTANCE_TYPE_ELITE_BEGIN = 25,
        INSTANCE_TYPE_ELITE_20 = 25,   //20级精英副本
        INSTANCE_TYPE_ELITE_30 = 26,   //30级精英副本
        INSTANCE_TYPE_ELITE_40 = 27,   //40级精英副本
        INSTANCE_TYPE_ELITE_50 = 28,   //50级精英副本
        INSTANCE_TYPE_ELITE_60 = 29,   //60级精英副本
        INSTANCE_TYPE_ELITE_70 = 30,   //70级精英副本
        INSTANCE_TYPE_ELITE_80 = 31,   //80级精英副本
        INSTANCE_TYPE_ELITE_90 = 32,   //90级精英副本
        INSTANCE_TYPE_ELITE_100 = 33,   //100级精英副本
        INSTANCE_TYPE_ELITE_110 = 34,   //110级精英副本
        INSTANCE_TYPE_ELITE_120 = 35,   //120级精英副本
        INSTANCE_TYPE_ELITE_130 = 36,   //130级精英副本
        INSTANCE_TYPE_ELITE_140 = 37,   //140级精英副本
        INSTANCE_TYPE_ELITE_150 = 38,   //150级精英副本
        INSTANCE_TYPE_ELITE_160 = 39,   //160级精英副本
        INSTANCE_TYPE_ELITE_END = 39,   


        INSTANCE_TYPE_MAX = 39,         //
    };

	CInstanceConfigData() 
    {
        bHasConifig = false;
	}

	virtual ~CInstanceConfigData() 
    {
	}

    //是否是秘境
    static bool IsSecret(unsigned char ucInstanceType)
    {
        if (ucInstanceType >= INSTANCE_TYPE_SECRET_LV20
            && ucInstanceType <= INSTANCE_TYPE_SECRET_LV160_HARD)
        {
            return true;
        }

        return false;
    }

    //是否是博物馆
    static bool IsMuseum(unsigned char ucInstanceType)
    {
        return (INSTANCE_TYPE_MUSEUM == ucInstanceType);
    }

    static bool IsElite(unsigned char ucInstanceType)
    {
        return (ucInstanceType >= INSTANCE_TYPE_ELITE_20 && ucInstanceType <= INSTANCE_TYPE_ELITE_160);
    }

public:
	bool bHasConifig;
    
    unsigned char   _ucInstanceType;     //副本类型
    unsigned short  _usInstanceID;       //副本ID
    //unsigned short  _usLevel;            //副本等级
    unsigned short  _usOpenLevel;        //副本开放等级

    int             _iRelatedTaskID;    //相关任务ID，这个任务完成后打开该副本
    unsigned char   _ucUseEnergy;       //消耗精力
    bool            _bHasSpecialBonus;  //是否有特殊奖励

    T_INSTANCE_MONSTER_GROUP_IDS _astMonsterGroupIDs; //怪物队伍id
    T_INSTANCE_MONSTER_GROUP_LEVELS _astMonsterGroupLevels;  //怪物等级
    T_INSTANCE_MONSTER_GROUP_POS _astMonsterGroupPos;        //怪物队伍位置

    T_DROP_ITEM_GROUP_CONFIG _astNormalDropItemGroup;        //普通怪物掉落
    T_DROP_ITEM_GROUP_CONFIG _astBossDropItemGroup;          //BOSS怪物掉落
    T_DROP_ITEM_GROUP_CONFIG _astInstanceDropItemGroup;      //副本掉落

    CInstanceFirstAccomplishBonusConfigData _stFirstBonus;   //首杀奖励
};

class CInstanceConfig
{
public:
    enum 
    {
        
    };

    CInstanceConfig()
    {
    }

    virtual ~CInstanceConfig()
    {

    }

    void Clear()
    {
        _astInstanceConfigData.Clear();
        for (int i = 0; i < MAX_INSTANCE_CONFIG_COUNT; ++i)
        {
            _astInstanceConfigData[i].bHasConifig = false;
        }
    }

    bool HasConfig(unsigned char ucInstanceType)
    {
        int iIndex = GetIndex(ucInstanceType, 1);
        if (iIndex <= 0 || iIndex >= MAX_INSTANCE_CONFIG_COUNT)
        {
            return false;
        }

        if (!_astInstanceConfigData[iIndex].bHasConifig)
        {
            return false;
        }

        return true;
    }

    int AddConfigData(CInstanceConfigData& stInstanceConfigData)
    {
        if (stInstanceConfigData._ucInstanceType < CInstanceConfigData::INSTANCE_TYPE_MIN 
            || stInstanceConfigData._ucInstanceType > CInstanceConfigData::INSTANCE_TYPE_MAX )
        {
            return ERROR_INSTANCE_TYPE;
        }

        if (stInstanceConfigData._ucInstanceType == CInstanceConfigData::INSTANCE_TYPE_MAIN)
        {
            if (stInstanceConfigData._usInstanceID >  MAX_INSTANCE_MAIN_CONFIG_COUNT)
            {
                return ERROR_INSTANCE_ID;
            }
        }
        else if (stInstanceConfigData._ucInstanceType == CInstanceConfigData::INSTANCE_TYPE_CHALLENGE)
        {
            if (stInstanceConfigData._usInstanceID >  MAX_INSTANCE_CHALLENGE_CONFIG_COUNT)
            {
                return ERROR_INSTANCE_ID;
            }
        }
        else 
        {
            if (stInstanceConfigData._usInstanceID > MAX_INSTANCE_BRANCH_CONFIG_COUNT)
            {
                return ERROR_INSTANCE_ID;
            }
        }

        int iIndex = GetIndex(stInstanceConfigData._ucInstanceType, stInstanceConfigData._usInstanceID);
        if (iIndex <= 0 || iIndex >= MAX_INSTANCE_CONFIG_COUNT)
        {
            return ERROR_INSTANCE_ADD_CONFIG;
        }

        if (_astInstanceConfigData[iIndex].bHasConifig)
        {
            CT_ERROR(("%d, %d", stInstanceConfigData._ucInstanceType, stInstanceConfigData._usInstanceID));
            return ERROR_INSTANCE_ADD_DUAL_CONFIG;
        }

        _astInstanceConfigData[iIndex] = stInstanceConfigData;
        _astInstanceConfigData[iIndex].bHasConifig = true;

        return 0;
    }

    int GetConfigData(unsigned char ucInstanceType, unsigned short usInstanceID, CInstanceConfigData& stInstanceConfigData)
    {
        int iIndex = GetIndex(ucInstanceType, usInstanceID);
        if (iIndex <= 0 || iIndex >= MAX_INSTANCE_CONFIG_COUNT)
        {
            return ERROR_INSTANCE_NO_CONFIG_DATA;
        }

        if (!_astInstanceConfigData[iIndex].bHasConifig)
        {
            return ERROR_INSTANCE_NO_CONFIG_DATA;
        }

        stInstanceConfigData = _astInstanceConfigData[iIndex];
        return 0;
    }

public:
    CTLib::CTArray<CInstanceConfigData, MAX_INSTANCE_CONFIG_COUNT> _astInstanceConfigData;

private:
    int GetIndex(unsigned char ucInstanceType, unsigned short usInstanceID)
    {
        if (ucInstanceType < CInstanceConfigData::INSTANCE_TYPE_MIN 
            || ucInstanceType > CInstanceConfigData::INSTANCE_TYPE_MAX )
        {
            return 0;
        }

        switch(ucInstanceType)
        {
        case CInstanceConfigData::INSTANCE_TYPE_MAIN:
            return usInstanceID;
        case CInstanceConfigData::INSTANCE_TYPE_CHALLENGE:
            return usInstanceID + MAX_INSTANCE_MAIN_CONFIG_COUNT;
        default:
            return MAX_INSTANCE_MAIN_CONFIG_COUNT + MAX_INSTANCE_CHALLENGE_CONFIG_COUNT + 
                (ucInstanceType - CInstanceConfigData::INSTANCE_TYPE_CHALLENGE) * MAX_INSTANCE_BRANCH_CONFIG_COUNT + usInstanceID;
        }
    }
};

//秘境配置
class CSecretInstanceConfigData
{
public:
    CSecretInstanceConfigData()
        :_bHasConfig(false)
    {

    }

public:
    bool _bHasConfig;

    unsigned char  _ucSecretID;         //秘境ID
    unsigned short _usOpenLevel;        //开放等级
    unsigned char  _ucInstanceType;     //副本类型
    unsigned char  _ucInstanceCount;    //副本数量
    unsigned char  _ucHardSecretType;   //困难模式秘境ID
    
    unsigned int   _uiDropBoxID;        //掉落用的礼包ID
    unsigned int   _uiShowBoxID;        //显示用的礼包ID
};

class CSecretInstanceConfig
{
public:
    CSecretInstanceConfig()
    {
        _astSecretInstanceConfigDatas.m_iUsedCount = _astSecretInstanceConfigDatas.GetCount();
    }

    int AddConfig(CSecretInstanceConfigData& stConfigData)
    {
        if (stConfigData._ucSecretID <= 0 
            || stConfigData._ucSecretID >= _astSecretInstanceConfigDatas.GetCount()
            || _astSecretInstanceConfigDatas[stConfigData._ucSecretID]._bHasConfig)
        {
            CT_ERROR(("%d", stConfigData._ucSecretID));
            return RET_SYS_ERROR;
        }

        _astSecretInstanceConfigDatas[stConfigData._ucSecretID] = stConfigData;
        _astSecretInstanceConfigDatas[stConfigData._ucSecretID]._bHasConfig = true;
        return 0;
    }

    bool IsValidSecretInstanceId (unsigned char ucSecretID)
    {
        if (ucSecretID >= _astSecretInstanceConfigDatas.GetCount()
            || !_astSecretInstanceConfigDatas[ucSecretID]._bHasConfig)
        {
            return false;
        }

        return true;
    }

    int GetConfig(unsigned char ucSecretID, CSecretInstanceConfigData& stConfigData)
    {
        if (ucSecretID <= 0 
            || ucSecretID >= _astSecretInstanceConfigDatas.GetCount()
            || !_astSecretInstanceConfigDatas[ucSecretID]._bHasConfig)
        {
            //CT_ERROR(("%d", ucSecretID));
            return RET_SYS_ERROR;
        }

        stConfigData = _astSecretInstanceConfigDatas[ucSecretID];
        return 0;
    }

public:
    CTLib::CTArray<CSecretInstanceConfigData, MAX_INSTANCE_SECRET_CONFIG_COUNT + 1> _astSecretInstanceConfigDatas;
};

//战斗评分配置
class CBattleScoreConfigData
{
public:
    CBattleScoreConfigData() 
    {
        Clear();
    }

    void Clear()
    {
        _iResID = 0;
        _iAttackScore = 0;
        _iAttackGrid = 0;
        _iDefendScore = 0;
        _iDefendGrid = 0;
        _iMarkStar = 0;
    }

    virtual ~CBattleScoreConfigData() 
    {
    }

    bool IsValidID() const
    {
        return (_iResID > 0 && _iResID <= MAX_INSTANCE_BATTLE_SCORE_COUNT);
    }

    int GetResID() const {return _iResID;}
    int GetAttackScore() const {return _iAttackScore;}
    int GetAttackGrid() const {return _iAttackGrid;}
    int GetDefendScore() const {return _iDefendScore;}
    int GetDefendGrid() const {return _iDefendGrid;}
    int GetMarkStar() const {return _iMarkStar;}

    void SetResID (int iResID) {_iResID = iResID;}
    void SetAttackScore(int iAttackScore){_iAttackScore = iAttackScore;}
    void SetAttackGrid(int iAttackGrid){_iAttackGrid = iAttackGrid;}
    void SetDefendScore(int iDefendScore){_iDefendScore = iDefendScore;}
    void SetDefendGrid(int iDefendGrid){_iDefendGrid = iDefendGrid;}
    void SetMarkStar(int iMarkStar){_iMarkStar = iMarkStar;}

private:
    int         _iResID;            //资源ID
    int         _iAttackScore;      //攻击得分
    int         _iAttackGrid;       //攻击格数
    int         _iDefendScore;      //防御得分
    int         _iDefendGrid;       //防御格数
    int         _iMarkStar;         //评价星级
};

class CBattleScoreConfig
{
public:
    CBattleScoreConfig() 
    {
    }

    virtual ~CBattleScoreConfig() 
    {
    }

    int AddConfig(CBattleScoreConfigData& stCfgData)
    {
        if (!stCfgData.IsValidID())
        {
            return ERROR_INSTANCE_OVER_RESID;
        }
    
        if (_astBattleScore[stCfgData.GetResID() - 1].IsValidID()) 
        {
            return ERROR_INSTANCE_REPEAT_RESID;
        }
    
        _astBattleScore[stCfgData.GetResID() - 1] = stCfgData;
    
        return 0;
    }
    
    int FindConfig(int iResID)
    {
        if (iResID > MAX_INSTANCE_BATTLE_SCORE_COUNT || iResID <= 0)
        {
            return -1;//因为返回下标 所以这里必须返回负数
        }
    
        if (!_astBattleScore[iResID - 1].IsValidID()) 
        {
            return -1;//因为返回下标 所以这里必须返回负数
        }
    
        if (iResID != _astBattleScore[iResID - 1].GetResID())
        {
            return -1;//因为返回下标 所以这里必须返回负数
        }
    
        return iResID - 1;
    }

    CBattleScoreConfigData& GetConfig(int iIndex){return _astBattleScore[iIndex];}

private:
    CTLib::CTArray<CBattleScoreConfigData, MAX_INSTANCE_BATTLE_SCORE_COUNT> _astBattleScore;
};

#endif // __CInstanceConfig_h__

